package socketTest;

import java.awt.*;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

public class Server {
    private ServerSocket serverSocket;
    private List<PrintWriter> allOut = new ArrayList<>();
    public Server(){//本类的构造
        try {
            System.out.println("正在启动服务器");
            //创建一个服务端，构造参数给一个端口号
            serverSocket = new ServerSocket(8089);
            System.out.println("服务端启动完毕");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void start(){
        try {
            while (true){
                System.out.println("等待客户端连接");
                //使用Socket定义一个标识符，接收来自客户端的信息(这个信息接收过来是字节流)
                Socket socket = serverSocket.accept();
                //实例化ClientHandler(内部类)，并把socket接收过来的信息放进构造ClientHandler构造中
                ClientHandler clientHandler = new ClientHandler(socket);
                //创建线程
                Thread t = new Thread(clientHandler);
                //执行线程中的自带start方法
                t.start();
                System.out.println("已连接客户端");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        //实例化服务端(本类)
        Server server = new Server();
        //执行服务端start方法
        server.start();
    }
    //定义一个类，实现Runnable接口,用来实现多线程
    public class ClientHandler implements Runnable{
        //定义一个标识符接收构造中的socket信息
        private Socket socket;
        //定义一个标识符定义该客户端的ip信息
        private String host;
        public ClientHandler(Socket socket){
            //构造中的接收过来的socket赋给this.socket
            this.socket = socket;
            //获取客户端的ip地址
            host =socket.getInetAddress().getHostAddress();
        }
        @Override
        public void run() {
            try {
                //创建一个输入流接收到socket的信息
                InputStream in = socket.getInputStream();
                //创建一个转换流，字节转换为字符，并设置为utf-8
                InputStreamReader isr = new InputStreamReader(in, StandardCharsets.UTF_8);
                //设置缓存流，可以使用readLine方法可以一行的读
                BufferedReader br = new BufferedReader(isr);

                //通过socket获取输出流用于给客户端发信息
                OutputStream os = socket.getOutputStream();
                //创建转换流
                OutputStreamWriter osw  = new OutputStreamWriter(os,StandardCharsets.UTF_8);
                //缓冲流
                BufferedWriter bw = new BufferedWriter(osw);
                //向文本输出流
                PrintWriter pw = new PrintWriter(bw,true);
                //将该输出流共享集合allOut
                allOut.add(pw);
                System.out.println(host+"上线了，当前在线人数:"+allOut.size());

                //定义一个标识符接收缓存流过来的信息
                String message = null;
                while ((message = br.readLine())!=null){//判定缓存流不等于空
                    //输出信息
                    System.out.println(host+"说："+message);
                    for(PrintWriter o:allOut){
                        //将消息回复给所有客户端
                        o.println(host+"说："+message);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
